/*
 * This file is part of Ember.
 *
 * Ember is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Ember is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Ember.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Copyright (C) Grant Tyra 2010
 * granttyra@gmail.com
*/

#include "ember_list_type.h"
#include "ember_class.h"
#include "ember_dictionary.h"
#include "ember_list.h"
#include "ember_call_stack.h"
#include "ember_types.h"
#include "ember_string.h"
#include <stdlib.h>

EmberObject *ember_dict_create(EmberDictionary *dict) {
    EmberObject *dictionary = EmberObjectCreate("Dictionary");
    EmberObjectPutAttribute(dictionary, "dict", dict); 
    return dictionary;
}

EmberObject *ember_dict_put() {
    EmberObject *ths = EmberCallStackRetrieve("this");
    EmberObject *key = EmberCallStackRetrieve("key");
	EmberObject *value = EmberCallStackRetrieve("value");
    EmberDictionary *dict = EmberObjectGetAttribute(ths, "dict");
    EmberDictionaryPut(dict, EmberStringValue(key), value);
    EmberObjectRetain(value);
    return value;
}

EmberObject *ember_dict_get() {
    EmberObject *ths = EmberCallStackRetrieve("this");
    EmberObject *key = EmberCallStackRetrieve("key");
    EmberDictionary *dict = EmberObjectGetAttribute(ths, "dict");
    EmberObject *value = EmberDictionaryGet(dict, EmberStringValue(key));
    return value;
}
EmberObject *ember_dict_remove() {
    EmberObject *ths = EmberCallStackRetrieve("this");
    EmberObject *key = EmberCallStackRetrieve("key");
    EmberDictionary *dict = EmberObjectGetAttribute(ths, "dict");
    EmberObject *value = EmberDictionaryGet(dict, EmberStringValue(key));
	EmberDictionaryRemove(dict, EmberStringValue(key));
    EmberObjectRelease(value);
	return value;
}

EmberObject *ember_dict_values() {
    EmberObject *ths = EmberCallStackRetrieve("this");
    EmberDictionary *dict = EmberObjectGetAttribute(ths, "dict");
    EmberList *values = EmberListCreate();
	EmberDictionaryValues(dict, values);
    return ember_list_create(values);
}

EmberObject *ember_dict_keys() {
    EmberObject *ths = EmberCallStackRetrieve("this");
    EmberDictionary *dict = EmberObjectGetAttribute(ths, "dict");
    EmberList *raw_keys = EmberListCreate();
	EmberList *ember_keys = EmberListCreate();
	int i = 0;
	EmberDictionaryKeys(dict, raw_keys);

	for (i = 0; i < raw_keys->size; i++) {
		EmberListAdd(ember_keys, EmberObjectCreateString(EmberListGet(raw_keys, i)));
	}

    return ember_list_create(ember_keys);
}

EmberObject *ember_dict_to_string() {
	EmberObject *ths = EmberCallStackRetrieve("this");
    EmberDictionary *dict = EmberObjectGetAttribute(ths, "dict");
	EmberObject *value = NULL;
	EmberList *keys = EmberListCreate();
	char *string = EmberStringCopy("{");
	int i = 0;

	EmberDictionaryKeys(dict, keys);

	for (i = 0; i < keys->size; i++) {
		EmberStringAppend(&string, "'");
		EmberStringAppend(&string, EmberListGet(keys, i));
		EmberStringAppend(&string, "' => ");
		value = EmberDictionaryGet(dict, EmberListGet(keys, i));
		EmberStringAppend(&string, value->classdef->name);
		EmberStringAppend(&string, ", ");
	}

	EmberStringAppend(&string, "NULL}");
	return EmberObjectCreateString(string);
}

void EmberDictionaryInstall() {
	EmberClassDef *classdef;
    classdef = EmberClassCreate("Dictionary", NULL);
    EmberDictionaryPut(classdef->instMethods, "put", EmberMethodCreate("key, value", 1, ember_dict_put));
    EmberDictionaryPut(classdef->instMethods, "get", EmberMethodCreate("key", 1, ember_dict_get));
    EmberDictionaryPut(classdef->instMethods, "remove", EmberMethodCreate("key", 1, ember_dict_remove));
    EmberDictionaryPut(classdef->instMethods, "keys", EmberMethodCreate("", 1, ember_dict_keys));
    EmberDictionaryPut(classdef->instMethods, "values", EmberMethodCreate("", 1, ember_dict_values));
	EmberDictionaryPut(classdef->instMethods, "toString", EmberMethodCreate("", 1, ember_dict_to_string));
    EmberClassMapPut(classdef);
}

void EmberListInstall() {
    EmberClassDef *classdef;
    classdef = EmberClassCreate("List", NULL);
    EmberDictionaryPut(classdef->instMethods, "add", EmberMethodCreate("arg", 1, ember_list_add));
    EmberDictionaryPut(classdef->instMethods, "get", EmberMethodCreate("index", 1, ember_list_get));
    EmberDictionaryPut(classdef->instMethods, "insert", EmberMethodCreate("arg, index", 1, ember_list_insert));
    EmberDictionaryPut(classdef->instMethods, "find", EmberMethodCreate("arg", 1, ember_list_find));
    EmberDictionaryPut(classdef->instMethods, "contains", EmberMethodCreate("arg", 1, ember_list_contains));
    EmberDictionaryPut(classdef->instMethods, "remove", EmberMethodCreate("arg", 1, ember_list_remove));
	EmberDictionaryPut(classdef->instMethods, "toString", EmberMethodCreate("", 1, ember_list_to_string));
	EmberDictionaryPut(classdef->instMethods, "count", EmberMethodCreate("", 1, ember_list_count));
    EmberClassMapPut(classdef);
}

EmberList *ember_list_value(EmberObject *obj) {
	return EmberObjectGetAttribute(obj, "list");
}

EmberObject *ember_list_count() {
	EmberObject *ths = EmberCallStackRetrieve("this");
    EmberList *list = EmberObjectGetAttribute(ths, "list");
	return EmberObjectCreateInteger(list->size);
}

EmberObject *ember_list_add() {
    EmberObject *ths = EmberCallStackRetrieve("this");
    EmberObject *obj = EmberCallStackRetrieve("arg");
    EmberList *list = EmberObjectGetAttribute(ths, "list");
    EmberListAdd(list, obj);
    EmberObjectRetain(obj);
    return obj;
}

EmberObject *ember_list_to_string() {
	EmberObject *ths = EmberCallStackRetrieve("this");
    EmberList *list = EmberObjectGetAttribute(ths, "list");
	EmberObject *element = NULL;
	char *string = EmberStringCopy("(");
	int i = 0;

	for (i = 0; i < list->size; i++) {
		element = EmberListGet(list, i);
		EmberStringAppend(&string, element->classdef->name);
		EmberStringAppend(&string, ", ");
	}

	EmberStringAppend(&string, "NULL)");
	return EmberObjectCreateString(string);
}

EmberObject *ember_list_get() {
    EmberObject *ths = EmberCallStackRetrieve("this");
    EmberObject *index = EmberCallStackRetrieve("index");

    EmberList *list = EmberObjectGetAttribute(ths, "list");
    return EmberListGet(list, EmberIntegerValue(index));
}

EmberObject *ember_list_insert() {
    EmberObject *ths = EmberCallStackRetrieve("this");
    EmberObject *index = EmberCallStackRetrieve("index");
    EmberObject *obj = EmberCallStackRetrieve("arg");
    EmberList *list = EmberObjectGetAttribute(ths, "list");
    EmberListSet(list, EmberIntegerValue(index), obj);
    EmberObjectRetain(obj);
    return obj;
}

EmberObject *ember_list_find() {
    EmberObject *ths = EmberCallStackRetrieve("this");
    EmberObject *obj = EmberCallStackRetrieve("arg");
    EmberList *list = EmberObjectGetAttribute(ths, "list");
    return EmberObjectCreateInteger(EmberListFind(list, obj));
}

EmberObject *ember_list_contains() {
    return EmberObjectCreateInteger(EmberIntegerValue(ember_list_find()) >= 0);
}

EmberObject *ember_list_remove() {
    EmberObject *ths = EmberCallStackRetrieve("this");
    EmberObject *obj = EmberCallStackRetrieve("arg");
    EmberList *list = EmberObjectGetAttribute(ths, "list");
	EmberObject *removed = EmberListGet(list, EmberIntegerValue(obj));
    EmberListRemove(list, EmberIntegerValue(obj));
	EmberObjectRelease(removed);
    return obj;
}

EmberObject *ember_list_create(EmberList *lst) {
    EmberObject *list = EmberObjectCreate("List");
    EmberObjectPutAttribute(list, "list", lst); 
    return list;
}


